#ifndef PHITERATIVERESOURCEMANAGER_H
#define PHITERATIVERESOURCEMANAGER_H

#include "PhResourceManager.h"
#include <boost/shared_ptr.hpp>
#include <vector>

namespace phoenix{

//! PhIterativeResourceManager template.
/*!
	A templated class for automatic garbage collection.
	This class is iterative safe, that means that after each
	iteration, you must call pruneList() in order to clear
	the list from the nodes you may have deleted during iteration.
	For iterative-safe version, please refer to
	PhIterativeResourceManager.
	\sa PhResourceManager
*/
template <typename T>
class PhIterativeResourceManager : public virtual PhResourceManager<T>
{
	public:

		PhIterativeResourceManager(const bool clean = true) : PhResourceManager<T>(clean) {}

		virtual ~PhIterativeResourceManager()
		{
			//prune nodes from deletion list
			pruneList();
			//PhResourceManager's destructor takes care of the rest.
		}

		//! Overloaded remove resource
		/*!
			Adds the given resource to the deletion list to be removed
			from the resource list with pruneList() is called.
			\sa PhResourceManager::removeResource()
		*/
		inline virtual void removeResource( boost::shared_ptr<T> rc )
		{
			deletionlist.push_back( rc );
		}

		//! Overloaded drop resources.
		/*!
			We'll overload the drop resources function because we need to make sure we
			call pruneList() before we go deleting invalid pointers.
		*/
		inline virtual void dropResources()
		{
			pruneList();
			PhResourceManager<T>::dropResources();
		}

		//! Prune list
		/*!
			Prunes every resource listed in the deletion list from the resource list.
		*/
		inline void pruneList()
		{
			// Run through the deletion list and remove nodes.
			for( typename std::vector<boost::shared_ptr<T> >::iterator i = deletionlist.begin(); i != deletionlist.end(); ++i )
			{
				for( typename std::vector< boost::shared_ptr<T> >::iterator j = this->resourcelist.begin(); j != this->resourcelist.end(); ++j)
				{
					if((*j)==(*i))
					{
						this->resourcelist.erase(j);
						break;
					}
				}
			}
			// no need to keep it populated anymore
			deletionlist.clear();
		}

		//! Clear deletion list
		/*!
			Clears the deletion list, preventing resources that are in it from being
			removed from the list.
			\note This is very dangerous and may lead to iterations on invalid pointers.
		*/
		inline void clearDeletionList() { deletionlist.clear(); }

		//! Deletion list size
		/*!
			Returns the size of the deletion list.
		*/
		inline const unsigned int getDeletionListSize() { return deletionlist.size(); }

		//! Get deletion list
		/*!
			Returns a reference to the deletion list.
			\sa getDeletionListCopy
		*/
		inline std::vector< boost::shared_ptr<T> >* getDeletionList() { return &deletionlist;}

		//! Get deletion list copy
		/*!
			Returns a const reference (copy) of the deletion list.
			\sa getDeletionList
		*/
		inline const std::vector< boost::shared_ptr<T> >& getDeletionListCopy() const { return deletionlist; }

	protected:
		std::vector< boost::shared_ptr<T> > deletionlist;
	private:
};

}//namespace phoenix

#endif // PHITERATIVERESOURCEMANAGER_H
